import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.*;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;


public class Main {
	// Global variables here
    static InstructionTable INSTRUCTION_TABLE;
    static int record_count;
    static int text_count;
    static int module_length;
	static String PROGRAM_NAME;
    static boolean continue_simulation;
    static String instruction = null;
	static int format;
	static boolean valid_end;
	static int dump_value = 0;
	static int register = 0;
	static int register2 = 0;
	static int x_register = 0;
	static int page = 0;
	static int page2 = 0;
	static int s_field = 0;
	static int dev = 0;
	static int type = 0;
	static int length = 0;
	static boolean jump_flag = false;
    
    // Set these for pass 2 during Pass 1
    static int exec_address = 0;
    static int exec_page = 0;
    static int LC = 0;
    
    // Memory Pages; first index is page, second index is address
    static String[][] memory = new String[4][4096];
    
    // Global registers
    static String[] global_reg = new String [8];
    static String[] global_xreg = new String [8];
    
	static ErrorHandler eHandler;
    private final static String newline = System.getProperty("line.separator");
	
	public static void main(String[] args) {
        INSTRUCTION_TABLE = new InstructionTable();
        INSTRUCTION_TABLE.LoadInstructionTable("InstructionTable.txt");
        
        eHandler = new ErrorHandler(); 
		createFrame();				
	}
	
	private static void createFrame() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
        
        JFrame frame = new JFrame("Group 02");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SimulatorFrame());
        frame.setMinimumSize(new Dimension(400, 700));
        frame.setVisible(true);    
        frame.setSize((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2, (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight()/2);
        frame.setLocation((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth()/4, (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight()/10);	
	}

	public static void run(File selectedFile) {
		record_count = 0;
		text_count = 0;
		continue_simulation = true;
		valid_end = false;

		initializeRegs();
		fillWithHalt();
		runSimulatorPassOne(selectedFile);

		if (continue_simulation)
		{
			if (valid_end) {
				runSimulatorPassTwo();
			}
			else {
				outputPrint("ERROR: LOADER FILE MUST HAVE A VALID END RECORD");
			}
		}	
	}
	
	private static void initializeRegs()
	{
		for (int i = 0; i < 8; i++)
		{
			global_reg[i] = "00000000";
		}
		
		for (int i = 0; i < 8; i++)
		{
			global_xreg[i] = "00000000";
		}
	}
	
	private static void fillWithHalt()
	{
		for (int i = 0; i < 4096; i ++)
		{
			memory[0][i] = "FC000000";
		}
		for (int i = 0; i < 4096; i ++)
		{
			memory[1][i] = "FC000000";
		}
		for (int i = 0; i < 4096; i ++)
		{
			memory[2][i] = "FC000000";
		}
		for (int i = 0; i < 4096; i ++)
		{
			memory[3][i] = "FC000000";
		}
	}
	
	private static void runSimulatorPassOne (File selectedFile) {

		try {
    		BufferedReader in = new BufferedReader(new FileReader(selectedFile));
    		String str = null;
    		while (((str = in.readLine()) != null) && continue_simulation) {
    			if(str.length()>0){
    				inputPrint(str);
    				if (str.contains(":")) {
    					checkRecord(str.split(":"));
    				}    				
    			}
    		}
    	}catch (IOException e){
    			
    	}
		
		//this is where we will test the 
    }
    
    private static void runSimulatorPassTwo () {
    	/*
    	 *  Here is where you'll read from you're intermediate arrays. Get the hex instruction/data word 
    	 *  and use:
    	 *  			INSTRUCTION_TABLE.getInstruction(String opcode)
    	 *  
    	 *  This should return the instruction name and you can do if-else statements to see which instruction
    	 *  method you should simulate.
    	 */
    	LC = exec_address;
    	String opcode = null;
    	boolean no_errors = true;

   
    	while ((LC < 4096) && (continue_simulation))
    	{
        	instruction = null;
        	format = 0;
        	register = 0;
        	register2 = 0;
        	x_register = 0;
        	page = 0;
        	page2 = 0;
        	s_field = 0;
        	dev = 0;
        	type = 0;
        	length = 0;
        	jump_flag = false;
	
    		//get the binary opcode of the current LC
    		opcode = getInstructionOpcode (LC);
  		
    		if (opcode.equals ("111111"))
    		{
    			continue_simulation = false;
    		}
    		
    		//get the instruction name of the above opcode
    		instruction = INSTRUCTION_TABLE.getInstruction(opcode);
    		
    		//get the format of the instruction to obtain required data elements
    		format = INSTRUCTION_TABLE.findFormat (instruction);   	
        	    		
    		//based on the format above, get the appropriate data values to be used in the instruction method
    		if (format == 1)
    		{
    			getDataFormat1 ();
    		}
    		else if (format == 2)
    		{
    			getDataFormat2 ();
    		}
    		else if (format == 3)
    		{
    			getDataFormat3 ();
    		}
    		else if (format == 5)
    		{
    			getDataFormat5 ();
    		}
    		else if (format == 6)
    		{
    			getDataFormat6 ();
    		}
    		else if (format == 7)
    		{
    			getDataFormat7 ();
    		}
    		    		
    		//call appropriate simulation based on opcode
    		//arithmetic block
    		if (opcode.equals ("000000"))
    		{
    			Add (register, x_register, page, s_field);
    		}
    		else if (opcode.equals ("000001"))
    		{
    			Sub (register, x_register, page, s_field);
    		}
    		else if (opcode.equals ("000010"))
    		{
    			Mpy (register, x_register, page, s_field);
    		}
    		else if (opcode.equals ("000011"))
    		{
    			Div (register, x_register, page, s_field);
    		}
    		else if (opcode.equals ("000100"))
    		{
    			Sqv (register, s_field);
    		}
    		else if (opcode.equals ("000101"))
    		{
    			AddR (register, register2);
    		}
    		else if (opcode.equals ("000110"))
    		{
    			SubR (register, register2);
    		}
    		else if (opcode.equals ("000111"))
    		{
    			MpyR (register, register2);
    		}
    		else if (opcode.equals ("001000"))
    		{
    			DivR (register, register2);
    		}
    		
    		//storage and retrieval block
    		else if (opcode.equals("011000"))
    		{	
    			Ldr (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("011001"))
    		{
    			Ldn (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("011010"))
    		{
    			Str (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("011011"))
    		{
    			Clr (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("011100"))
    		{
    			ClrA();
    		}
    		else if (opcode.equals("011101"))
    		{
    			ClrX();
    		}
    		else if (opcode.equals("011110"))
    		{
    			Swr (register, register2);
    		}
    		else if (opcode.equals("010000"))
    		{
    			Srl (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("010001"))
    		{
    			Sll (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("010010"))
    		{
    			Sra (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("010011"))
    		{
    			Sla (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("010100")){
    			Rol (register, s_field);
    		}
    		else if (opcode.equals("010101"))
    		{
    			Ror (register, s_field);
    		}
    		else if (opcode.equals("001001"))
    		{
    			Anl (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("001010"))
    		{
    			Orl (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("001011"))
    		{
    			Ana (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("001100"))
    		{
    			Ora (register, x_register, page, s_field);
    		}
    		else if (opcode.equals("100000"))
    		{
    			Jeq ();
    		}
    		else if (opcode.equals("100001"))
    		{
    			Jlt ();
    		}
    		else if (opcode.equals("100010"))
    		{
    			Jgt ();
    		}
    		else if (opcode.equals("100011"))
    		{
    			Jmp ();
    		}
    		else if (opcode.equals("100100"))
    		{
    			Jlk ();
    		}
    		else if (opcode.equals("100101"))
    		{
    			Jdr ();
    		}
    		else if (opcode.equals("100110"))
    		{
    			JeqX ();
    		}
    		else if (opcode.equals("100111"))
    		{
    			JneqX ();
    		}
    		else if (opcode.equals("111000"))
    		{
    			LdX (x_register, page, s_field);
    		}
    		else if (opcode.equals("111001"))
    		{
    			AddX (x_register, page, s_field);
    		}
    		else if (opcode.equals("111101"))
    		{
    			Swp (page, page2);
    		}
    		else if (opcode.equals("111110"))
    		{
    			Dmp (s_field);
    		}
    		else if (opcode.equals("101000"))
    		{
    			//Wdv (dev, x_register, s_field, type, length);
    		}
    		else if (opcode.equals("101001"))
    		{
    			//Rdv (dev, x_register, s_field, type, length);
    		}
    		else
    		{
    			//Print error, invalid instruction
    			errorsPrint(eHandler.getError(35));
    			outputPrint(eHandler.getError(35));
		
    		}
    		//check if instruction is jump
    		if (!jump_flag)
    		{
    			LC++;
    		}
    	}
    	if (LC > 4095){
    		//PRINT ERROR MEMORY OUT OF BOUNDS
			errorsPrint(eHandler.getError(36));
			no_errors = false;
    	}
    	else 
    	{
    		if (dump_value == 1)
    		{
    			dumpMemory1();
    		}
    		else if (dump_value == 2)
    		{
    			dumpMemory2();
    		}
    		else if (dump_value == 3)
    		{
    			dumpMemory3();
    		}
    		if (no_errors)
    		outputPrint("Program ended successfully.");
    	}
    	if (LC == 0 && opcode.equals ("111111"));
    	{
    		errorsPrint(eHandler.getError(35));
    		outputPrint(eHandler.getError(35));
    	}
    }
    
    // Return true if operation results in overflow
    private static boolean testForOverflow (long value)
    {
    	boolean result = false;
    	
    	if ((value < -2147483648) || (value > 2147483647))
    	{
    		result = true;
    	}
    	
    	return result;
    }
    
    private static String extendHex (String hex, int digits) {
        while (hex.length() < digits) {
            hex = "0" + hex;
        }
        return hex;
    }
    
    /*
     * For the dump instruction
     * 		-If dump 1
     * 			-output last word hex according to format 1
     * 			-output reg values
     * 		-If dump 2 or 3
     * 			-for dump 2, do above then...
     * 			-iterate through memory printing the word hex info, reg at 8 per line
     */
    private static void dumpMemory1()
    {
    	if (LC > 4095)
    	{
    		LC = 4095;
    	}
    	//output to GUI current LC word / register values according to specs
    	String str = Integer.toHexString(LC);
    	extendHex (str, (6-str.length()));
    	outputPrint ("LC " + 0 + str.toUpperCase() + " WORD=" + memory[0][LC]);
    	outputPrint ("R0=" + global_reg[0] + " R1=" + global_reg[1] + " R20=" + global_reg[2] + " R3=" + global_reg[3] + " R4=" + global_reg[4] + " R5=" + global_reg[5] + " R6=" + global_reg[6] + " R7=" + global_reg[7]);
    	outputPrint ("R1=" + global_xreg[1] + " R20=" + global_xreg[2] + " R3=" + global_xreg[3] + " R4=" + global_xreg[4] + " R5=" + global_xreg[5] + " R6=" + global_xreg[6] + " R7=" + global_xreg[7]);
    }
    
    private static void dumpMemory2()
    {
    	//output all cells of memory of all pages
    	if (LC > 4095)
    	{
    		LC = 4095;
    	}
    	int i = 0;
    	while (i < 4088)
    	{
    		outputPrint(00 + i + memory[0][i] + memory[0][i+1] + memory[0][i+2] + memory[0][i+3] + memory[0][i+4] + memory[0][i+5] + memory[0][i+6] + memory[0][i+7]);
    		i = i + 8;
    	}
    	outputPrint(00 + i + memory[0][i] + memory[0][i+1] + memory[0][i+2] + memory[0][i+3] + memory[0][i+4] + memory[0][i+5] + memory[0][i+6] + memory[0][i+7]);

    	
    }
    
    private static void dumpMemory3()
    {
    	//output to GUI current LC word / register values according to specs
    	//output all cells of memory of all pages
    	if (LC > 4095)
    	{
    		LC = 4095;
    	}
    	//output to GUI current LC word / register values according to specs
    	String str = Integer.toHexString(LC);
    	outputPrint ("LC " + 0 + str.toUpperCase() + " WORD=" + memory[0][LC]);
    	outputPrint ("R0=" + global_reg[0] + " R1=" + global_reg[1] + " R20=" + global_reg[2] + " R3=" + global_reg[3] + " R4=" + global_reg[4] + " R5=" + global_reg[5] + " R6=" + global_reg[6] + " R7=" + global_reg[7]);
    	outputPrint ("R1=" + global_xreg[1] + " R20=" + global_xreg[2] + " R3=" + global_xreg[3] + " R4=" + global_xreg[4] + " R5=" + global_xreg[5] + " R6=" + global_xreg[6] + " R7=" + global_xreg[7]);
    
    	outputPrint ("");
    	if (LC > 4095)
    	{
    		LC = 4095;
    	}
    	
    	int i = 0;
    	
    	while (i < 4088)
    	{
    		outputPrint("00," + i + " " + memory[0][i] + " " + memory[0][i+1] + " "  + memory[0][i+2] + " "  + " "  + memory[0][i+3] + " "  + memory[0][i+4] + " "  + memory[0][i+5] + " "  + memory[0][i+6] + " "  + memory[0][i+7] + " " );
    		i = i + 8;
    	}
    	outputPrint(00 + i + " " +  memory[0][i] + " "  + memory[0][i+1] + " "  + memory[0][i+2] + " "  + memory[0][i+3] + " "  + memory[0][i+4] + " "  + memory[0][i+5] + " "  + memory[0][i+6] + " "  + memory[0][i+7] + " " );

    	i = 0;
    	
    	while (i < 4088)
    	{
    		outputPrint("01," + i + " " + memory[0][i] + " " + memory[0][i+1] + " "  + memory[0][i+2] + " "  + " "  + memory[0][i+3] + " "  + memory[0][i+4] + " "  + memory[0][i+5] + " "  + memory[0][i+6] + " "  + memory[0][i+7] + " " );
    		i = i + 8;
    	}
    	outputPrint("01," + i + " " +  memory[0][i] + " "  + memory[0][i+1] + " "  + memory[0][i+2] + " "  + memory[0][i+3] + " "  + memory[0][i+4] + " "  + memory[0][i+5] + " "  + memory[0][i+6] + " "  + memory[0][i+7] + " " );

    	i = 0;
    	
    	while (i < 4088)
    	{
    		outputPrint("02," + i + " " + memory[0][i] + " " + memory[0][i+1] + " "  + memory[0][i+2] + " "  + " "  + memory[0][i+3] + " "  + memory[0][i+4] + " "  + memory[0][i+5] + " "  + memory[0][i+6] + " "  + memory[0][i+7] + " " );
    		i = i + 8;
    	}
    	outputPrint("02," + i + " " +  memory[0][i] + " "  + memory[0][i+1] + " "  + memory[0][i+2] + " "  + memory[0][i+3] + " "  + memory[0][i+4] + " "  + memory[0][i+5] + " "  + memory[0][i+6] + " "  + memory[0][i+7] + " " );

    	i = 0;
    	
    	while (i < 4088)
    	{
    		outputPrint("03," + i + " " + memory[0][i] + " " + memory[0][i+1] + " "  + memory[0][i+2] + " "  + " "  + memory[0][i+3] + " "  + memory[0][i+4] + " "  + memory[0][i+5] + " "  + memory[0][i+6] + " "  + memory[0][i+7] + " " );
    		i = i + 8;
    	}
    	outputPrint("03," + i + " " +  memory[0][i] + " "  + memory[0][i+1] + " "  + memory[0][i+2] + " "  + memory[0][i+3] + " "  + memory[0][i+4] + " "  + memory[0][i+5] + " "  + memory[0][i+6] + " "  + memory[0][i+7] + " " );

    }
    
    /*
     * For Arithmetic instructions
     * 		-calculate the effective address by adding the s-field with the value in the index register
     * 		-convert the value of register R and effective memory address S(X) from string to long
     * 		-perform operation simulation
     * 		-test for overflow and division by zero (if applicable)
     * 		-convert long to string and store in register R
     */
    private static void Add (int register, int x_register, int page, int s_field)
    {
    	long operation_value;
    	
    	//convert reg value to int and add to s-field
    	int effect_addr = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    	
    	operation_value = Long.parseLong(memory[page][effect_addr],16) + Long.parseLong(global_reg[register],16);
    	
    	if (testForOverflow (operation_value))
    	{
    		//PRINT OVERFLOW ERROR
			errorsPrint(eHandler.getError(34));
    	}
    	else
    	{
    		global_reg[register] = Long.toHexString(operation_value);
    		outputPrint ("ADD " + register + "," + page + s_field + " = " + operation_value);
    	}
    }
    
    private static void Sub (int register, int x_register, int page, int s_field)
    {
    	long operation_value;
    	
    	//convert reg value to int and add to s-field
    	int effect_addr = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    	
    	operation_value = Long.parseLong(global_reg[register],16) - Long.parseLong(memory[page][effect_addr],16);
    	
    	if (testForOverflow (operation_value))
    	{
    		//PRINT OVERFLOW ERROR
			errorsPrint(eHandler.getError(34));
    	}
    	else
    	{
    		global_reg[register] = Long.toHexString(operation_value);
    		outputPrint ("SUB " + register + "," + page  + s_field + " = " + operation_value);
    	}
    }
    
    private static void Mpy (int register, int x_register, int page, int s_field)
    {
    	long operation_value;
    	
    	//convert reg value to int and add to s-field
    	int effect_addr = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    	
    	operation_value = Long.parseLong(memory[page][effect_addr],16) * Long.parseLong(global_reg[register],16);
    	
    	if (testForOverflow (operation_value))
    	{
    		//PRINT OVERFLOW ERROR
			errorsPrint(eHandler.getError(34));
    	}
    	else
    	{
    		global_reg[register] = Long.toHexString(operation_value);
    		outputPrint ("MPY " + register + "," + page  + s_field + " = " + operation_value);
    	}
    }
    
    private static void Div (int register, int x_register, int page, int s_field)
    {
    	long operation_value;
    	
    	//convert reg value to int and add to s-field
    	int effect_addr = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    	
    	if ((int)Long.parseLong(memory[page][effect_addr],16) == 0)
    	{
    		//PRINT DIVISION BY 0 ERROR
			errorsPrint(eHandler.getError(4));
    	}
    	else
    	{
    		operation_value = Long.parseLong(global_reg[register],16) / Long.parseLong(memory[page][effect_addr],16);
    	

    		if (testForOverflow (operation_value))
    		{
    			//PRINT OVERFLOW ERROR
    			errorsPrint(eHandler.getError(34));
    		}
    		else
    		{
    			global_reg[register] = Long.toHexString(operation_value);
        		outputPrint ("Register " + register + " / Location " + page + "," + s_field + " = " + operation_value);
    		}
    	}
    }
    
    private static void Sqv (int register, int s_field)
    {
    	long power = s_field;
    	long constant = Long.parseLong(global_reg[register]);
    	long operation_value = constant;
    	
    	//while loop to replicate power function
    	while (power > 1)
    	{
    		operation_value = operation_value * constant;
    		power--;
    	}
    	
    	if (testForOverflow (operation_value))
    	{
    		//PRINT OVERFLOW ERROR
			errorsPrint(eHandler.getError(34));
    	}
    	else
    	{
    		global_reg[register] = Long.toHexString(operation_value);
    		outputPrint ("Register " + register + " ^ Location " + page + "," + s_field + " = " + operation_value);
    	}
    }
    
    private static void AddR (int register, int register2)
    {
    	long operation_value = Long.parseLong(global_reg[register],16) + Long.parseLong(global_reg[register2],16);
    	
    	if (testForOverflow (operation_value))
    	{
    		//PRINT OVERFLOW ERROR
    		errorsPrint(eHandler.getError(34));
    	}
    	else
    	{
    		global_reg[register] = Long.toHexString(operation_value);
    		outputPrint ("Register " + register + " + Register " + register2 + " = " + operation_value);
    	}
    }
    
    private static void SubR (int register, int register2)
    {
    	long operation_value = Long.parseLong(global_reg[register],16) - Long.parseLong(global_reg[register2],16);
    	
    	if (testForOverflow (operation_value))
    	{
    		//PRINT OVERFLOW ERROR
    		errorsPrint(eHandler.getError(34));
    	}
    	else
    	{
    		global_reg[register] = Long.toHexString(operation_value);
    		outputPrint ("Register " + register + " - Register " + register2 + " = " + operation_value);
    	}
    }
    
    private static void MpyR (int register, int register2)
    {
    	long operation_value = Long.parseLong(global_reg[register],16) * Long.parseLong(global_reg[register2],16);
    	
    	if (testForOverflow (operation_value))
    	{
    		//PRINT OVERFLOW ERROR
    		errorsPrint(eHandler.getError(34));
    	}
    	else
    	{
    		global_reg[register] = Long.toHexString(operation_value);
    		outputPrint ("Register " + register + " * Register " + register2 + " = " + operation_value);
    	}
    }
    
    private static void DivR (int register, int register2)
    {
    	long operation_value = Long.parseLong(global_reg[register],16) / Long.parseLong(global_reg[register2],16);
    	
    	if (testForOverflow (operation_value))
    	{
    		//PRINT OVERFLOW ERROR
    		errorsPrint(eHandler.getError(34));
    	}
    	else
    	{
    		global_reg[register] = Long.toHexString(operation_value);
    		outputPrint ("Register " + register + " / Register " + register2 + " = " + operation_value);
    	}
    }
    
    /*
     * For storage and retrieval instructions
     * 		-calculate the effective address by adding the s-field with the value in the index register
     * 		-perform operation simulation
     * 		-convert long to string and store in register R
     */
    private static void Ldr (int register, int x_register, int page, int s_field)
    {
    	int effect_addr = ((int)Long.parseLong(global_xreg[x_register],16)) + s_field;    	 	

    	global_reg[register] = memory[page][effect_addr];
    	outputPrint("LDR " + register + "," + effect_addr);
    }
    
    private static void Ldn (int register, int x_register, int page, int s_field)
    {
    	int load_value = -((int)Long.parseLong(global_xreg[x_register],16) + s_field);
    	int effect_addr = ((int)Long.parseLong(global_xreg[x_register],16)) + s_field;   
    	if (testForOverflow (load_value))
    	{
    		//PRINT OVERFLOW ERROR
    		errorsPrint(eHandler.getError(34));
    	}
    	else
    	{
    		global_reg[register] = Integer.toHexString(load_value);
    		outputPrint("LDN " + register + "," + effect_addr);
    	}
    }
    
    private static void Str (int register, int x_register, int page, int s_field)
    {
    	int effect_addr = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    	
    	memory[page][effect_addr] = global_reg[register];
    	outputPrint("STR " + register + "," + effect_addr);
    }
    
    private static void Clr (int register, int x_register, int page, int s_field)
    {
    	int clear = 0;
    	
    	global_reg[register] = Integer.toString(clear);
    	outputPrint("CLR");
    }
    
    private static void ClrA ()
    {
    	int clear = 0;
    	
    	global_reg[0] = Integer.toString(clear);
    	global_reg[1] = Integer.toString(clear);
    	global_reg[2] = Integer.toString(clear);
    	global_reg[3] = Integer.toString(clear);
    	global_reg[4] = Integer.toString(clear);
    	global_reg[5] = Integer.toString(clear);
    	global_reg[6] = Integer.toString(clear);
    	global_reg[7] = Integer.toString(clear);
    	outputPrint("CLRA");
    }
    
    private static void ClrX ()
    {
 	int clear = 0;
    	
    	global_xreg[1] = Integer.toString(clear);
    	global_xreg[2] = Integer.toString(clear);
    	global_xreg[3] = Integer.toString(clear);
    	global_xreg[4] = Integer.toString(clear);
    	global_xreg[5] = Integer.toString(clear);
    	global_xreg[6] = Integer.toString(clear);
    	global_xreg[7] = Integer.toString(clear);
    	outputPrint("CLRX");
    }
    
    private static void Swr (int register, int register2)
    {
    	String temp = null;
    	
    	temp = global_reg[register2];
    	
    	global_reg[register2] = global_reg[register];
    	global_reg[register] = temp;
    	outputPrint("Register " + register + " &= " + "Register "+ register2);
    }
    
    /*
     * For shift and manipulate instructions
     * 		-check the s-field for values > 32
     * 		-convert the register string to int
     * 		-apply java shift operator

     */
    
    private static void Srl (int register, int x_register, int page, int s_field)
    {
    	if (s_field > 32)
    	{
    		//PRINT SHIFT GREATER THAN 32 ERROR
    		errorsPrint(eHandler.getError(5));
    	}
    	else
    	{
    		int reg_value = (int)Long.parseLong(global_reg[register]);
    		
    		global_reg[register] = Integer.toHexString(reg_value >>> s_field);
    		outputPrint("SRL " + register + "," + s_field + " = " + (reg_value >>> s_field));
    	}
    }
    
    private static void Sll (int register, int x_register, int page, int s_field)
    {
    	if (s_field > 32)
    	{
    		//PRINT SHIFT GREATER THAN 32 ERROR
    		errorsPrint(eHandler.getError(5));
    	}
    	else
    	{
    		int reg_value = (int)Long.parseLong(global_reg[register]);
    		
    		global_reg[register] = Integer.toHexString(reg_value << s_field);
    		outputPrint("SLL " + register + "," + s_field + " = " + (reg_value << s_field));
    	}
    }
         
    private static void Sra (int register, int x_register, int page, int s_field)
    {
    	if (s_field > 32)
    	{
    		//PRINT SHIFT GREATER THAN 32 ERROR
    		errorsPrint(eHandler.getError(5));
    	}
    	else
    	{
    		int reg_value = (int)Long.parseLong(global_reg[register],16);
    		
    		global_reg[register] = Integer.toHexString(reg_value >> s_field);
    		outputPrint("SRA " + register + "," + s_field + " = " + (reg_value >> s_field));
    	}
    }
    
    private static void Sla (int register, int x_register, int page, int s_field)
    {
    	if (s_field > 32)
    	{
    		//PRINT SHIFT GREATER THAN 32 ERROR
    		errorsPrint(eHandler.getError(5));
    	}
    	else
    	{
    		int reg_value = (int)Long.parseLong(global_reg[register]);
    		
    		global_reg[register] = Integer.toHexString(reg_value << s_field);
    		outputPrint("SLA " + register + "," + s_field + " = " + (reg_value << s_field));
    	}
    }
    
    private static void Rol (int register, int s_field)
    {
    	if (s_field > 32)
    	{
    		//PRINT rotate GREATER THAN 32 ERROR
    		errorsPrint(eHandler.getError(6));
    	}
    	else
    	{
    		int reg_value  = (int)Long.parseLong(global_reg[register],16);
    		global_reg[register] = Integer.toHexString(Integer.rotateLeft(reg_value, s_field));
    		outputPrint("ROL " + register + "," + s_field + " = " + (Integer.rotateLeft(reg_value, s_field)));
    	}
    }
    
    private static void Ror (int register, int s_field)
    {
    	if (s_field > 32)
    	{
    		//PRINT rotate GREATER THAN 32 ERROR
    		errorsPrint(eHandler.getError(6));
    	}
    	else
    	{
    		int reg_value  = (int)Long.parseLong(global_reg[register],16);
    		global_reg[register] = Integer.toHexString(Integer.rotateRight(reg_value, s_field));
    		outputPrint("ROR " + register + "," + s_field + " = " + (Integer.rotateRight(reg_value, s_field)));
    	}
    }
    
    /*
     * For logical
     * 		-convert the register value and the value at the effective address to int
     * 		-simulate bitwise logic operation
     * 		-store value as hex string in specified register
     */
    private static void Anl (int register, int x_register, int page, int s_field)
    {
    	int reg_value = (int)Long.parseLong(global_reg[register], 16);
    	int effect_addr = (int)Long.parseLong(memory[page][s_field], 16);
    		
    	global_reg[register] = Integer.toHexString(reg_value & effect_addr);
    	outputPrint("ANL " + register + "," + effect_addr + " = " + (reg_value & effect_addr));
    }
    
    private static void Orl (int register, int x_register, int page, int s_field)
    {
    	int reg_value = (int)Long.parseLong(global_reg[register], 16);
    	int effect_addr = (int)Long.parseLong(memory[page][s_field], 16);
    		
    	global_reg[register] = Integer.toHexString(reg_value ^ effect_addr);
    	outputPrint("ANL " + register + "," + effect_addr + " = " + (reg_value | effect_addr));
    }
    
    private static void Ana (int register, int x_register, int page, int s_field)
    {
    	int reg_value = (int)Long.parseLong(global_reg[register], 16);
    	int effect_addr = (int)Long.parseLong(memory[page][s_field], 16);
    		
    	global_reg[register] = Integer.toHexString(reg_value & effect_addr);
    	outputPrint("ANL " + register + "," + effect_addr + " = " + (reg_value & effect_addr));
    }
    
    private static void Ora (int register, int x_register, int page, int s_field)
    {
    	int reg_value = (int)Long.parseLong(global_reg[register], 16);
    	int effect_addr = (int)Long.parseLong(memory[page][s_field], 16);
    		
    	global_reg[register] = Integer.toHexString(reg_value | effect_addr);
    	outputPrint("ANL " + register + "," + effect_addr + " = " + (reg_value | effect_addr));
    }
    
    /*
     * For jump, test, and control instructions
     * 		-convert the register value from string to int
     * 		-compare register value to instruction jump trigger
     * 		-if jump is triggered, set jump_flag to true and set LC to the value at the effective address
     */
    private static void Jeq ()
    {
    	int reg_value = (int)Long.parseLong(global_reg[register], 16);
    	
    	if (reg_value == 0)
    	{
    		LC = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    		jump_flag = true;
    		outputPrint("JEQ " + register + "," + LC);
    		
    	}
    }

    private static void Jlt ()
    {
    	int reg_value = (int)Long.parseLong(global_reg[register],16);
    	if (reg_value < 0)
    	{
    		LC = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    		jump_flag = true;
    		outputPrint("JLT " + register + "," + LC);
    	}
    }
    
    private static void Jgt ()
    {
    	int reg_value = (int)Long.parseLong(global_reg[register], 16);
    	
    	if (reg_value > 0)
    	{
    		LC = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    		jump_flag = true;
    		outputPrint("JGT " + register + "," + LC);
    	}
    }
    
    private static void Jmp ()
    {   	
    	LC = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    	jump_flag = true;
    	outputPrint("JMP " + register + "," + LC);
    }
    
    private static void Jlk ()
    {
    	global_reg[register] = Integer.toHexString(LC + 1);
    	 	
    	LC = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    	jump_flag = true;
    	outputPrint("JLK " + register + "," + LC);
    }
    
    private static void Jdr ()
    {
    	int reg_value = (int)Long.parseLong(global_reg[register], 16);
    	reg_value--;
    	global_reg[register] = Integer.toHexString(reg_value);
    	
    	if (reg_value == 0)
    	{
    		LC = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    		jump_flag = true;
    		outputPrint("JDR " + register + "," + LC);
    	}
    }
    
    private static void JeqX ()
    {
    	int reg_value = (int)Long.parseLong(global_reg[x_register], 16);
    	
    	if (reg_value == 0)
    	{
    		LC = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    		jump_flag = true;
    		outputPrint("JEQX " + register + "," + LC);
    	}
    }
    
    private static void JneqX ()
    {
    	outputPrint(global_xreg[1]);
    	int reg_value = (int)Long.parseLong(global_reg[x_register], 16);
    	
    	if (reg_value != 0)
    	{
    		LC = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    		jump_flag = true;
    		outputPrint("JNEQX " + register + "," + LC);
    	}
    }
    
    /*
     * For index register operations
     * 		-set the index register equal to the string at the effective address
     */
    
    private static void LdX (int x_register, int page, int s_field)
    {
    	int effect_addr = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    	
    	global_reg[x_register] = memory[page][effect_addr];
    	outputPrint ("LDX " + x_register + "," + effect_addr);
    }
    
    private static void AddX (int x_register, int page, int s_field)
    {
    	int effect_addr = (int)Long.parseLong(global_xreg[x_register],16) + s_field;
    	int reg_value = (int)Long.parseLong(global_reg[x_register],16);
    	int addr_value = (int)Long.parseLong(memory[page][s_field],16);
    	   	
    	global_reg[x_register] = Integer.toHexString(reg_value + addr_value);
    }
    
    private static void Swp (int page, int page2)
    {
    	String[][] temp = new String[4][4095];
    	
    	for (int i = 0; i < 4095; i++)
    	{
    		temp[page][i] = memory[page][i];
    	}
    	
    	for (int i = 0; i < 4095; i++)
    	{
    		memory[page2][i] = memory[page][i];
    	}
    	
    	for (int i = 0; i < 4095; i++)
    	{
    		memory[page][i] = temp[page][i];
    	}
    	
    	outputPrint("SWP " + page + "," + page2);
    }
    
    private static void Dmp (int s_field)
    {
   
    	dump_value = s_field;
    	outputPrint ("DMP " + dump_value);
    }
    
    private static void Wdv (int dev, int x_register, int s_field, int type, int length)
    {
    	outputPrint ("WDV " + dev + "," + s_field + "(" + x_register + ")" + "," + type + "," + length);
    }
    
    private static void Rdv (int dev, int x_register, int s_field, int type, int length)
    {
    	outputPrint ("RDV " + dev + "," + s_field + "(" + x_register + ")" + "," + type + "," + length);
    }
    
    private static String getInstructionOpcode (int LC)
    {
    	String binary_opcode = null;
    	String binary_instruction = null;
    	String instruction = memory[0][LC];
    	
    	//convert the hex string in memory to binary, then return the first 6 digits (the opcode)
    	binary_instruction = hexToBinary (instruction);
    	binary_opcode = binary_instruction.substring(0,6);
    	
    	return binary_opcode;
    }   
    
    private static void getDataFormat1 ()
    {
    	String instruction = null;
    	String temp = null;
    	
    	//convert Hex instruction to binary string
    	temp = memory[0][LC];
    	instruction = hexToBinary(temp);
    	
    	//get register value
    	temp = instruction.substring (6,9);
    	register = (int)Long.parseLong(temp, 2);
    	
    	//get x_register value
    	temp = instruction.substring (9,12);
    	x_register = (int)Long.parseLong (temp, 2);
    	
    	//get page value
    	temp = instruction.substring (14,16);
    	page = (int)Long.parseLong(temp, 2);
    	
    	//get s_field value
    	temp = instruction.substring (20,32);
    	s_field = (int)Long.parseLong(temp, 2);
    }
    
    private static void getDataFormat2 ()
    {
    	String instruction = null;
    	String temp = null;
    	
    	//convert Hex instruction to binary string
    	temp = memory[0][LC];
    	instruction = hexToBinary(temp);
    	
    	//get register value
    	temp = instruction.substring (6,9);
    	register = (int)Long.parseLong (temp, 2);
    	
    	//get s_field value
    	temp = instruction.substring(20,32);
    	s_field = (int)Long.parseLong (temp, 2);
    }
    
    private static void getDataFormat3 ()
    {
    	String instruction = null;
    	String temp = null;
    	
    	//convert Hex instruction to binary string
    	temp = memory[0][LC];
    	instruction = hexToBinary(temp);
    	
    	//get s_field value
    	temp = instruction.substring(20,32);
    	s_field = (int)Long.parseLong (temp,2);
    }
    
    private static void getDataFormat5 ()
    {
    	String instruction = null;
    	String temp = null;
    	
    	//convert Hex instruction to binary string
    	temp = memory[0][LC];
    	instruction = hexToBinary(temp);
    	
    	//get dev value
    	temp = instruction.substring(6,9);
    	dev = (int)Long.parseLong(temp,2);
    	
    	//get s_field value
    	temp = instruction.substring (20,32);
    	s_field	= (int)Long.parseLong(temp,2);
    	
    	//get x_register
    	temp = instruction.substring(9,12);
    	x_register = (int)Long.parseLong(temp,2);
    	
    	//get type value
    	temp = instruction.substring(12,14);
    	type = (int)Long.parseLong(temp,2);
    	
    	//get page value
    	temp = instruction.substring(14,16);
    	page = (int)Long.parseLong(temp,2);
    	
    	//get length value
    	temp = instruction.substring(16,20);
    	length = (int)Long.parseLong(temp,2);
    }
    
    private static void getDataFormat6 ()
    {
    	String instruction = null;
    	String temp = null;
    	
    	//convert Hex instruction to binary string
    	temp = memory[0][LC];
    	instruction = hexToBinary(temp);
    	
    	//get page2 value
    	temp = instruction.substring(12,14);
    	page2 = (int)Long.parseLong(temp,2);
    	
    	//get page value
    	temp = instruction.substring(14,16);
    	page = (int)Long.parseLong(temp,2);
    }
    
    private static void getDataFormat7 ()
    {
    	String instruction = null;
    	String temp = null;
    	
    	//convert Hex instruction to binary string
    	temp = memory[0][LC];
    	instruction = hexToBinary(temp);
    	
    	//get register value
    	temp = instruction.substring(6,9);
    	register = (int)Long.parseLong(temp,2);
    	
    	//get register2 value
    	temp = instruction.substring(9,12);
    	register2 = (int)Long.parseLong(temp,2);    	
    }
    
    private static void checkRecord (String[] tokens) {
    	/* 
    	 *   checkRecord takes the array of tokens that was split by ":" and calls the appropriate method
    	 *   to check the syntax of the record appropriately
    	 */
    	
    	if (tokens[0].equals("H")) {
    		checkHeaderRecord(tokens);
    		record_count++;
    	}
    	else if (tokens[0].equals("T")) {
    		checkTextRecord(tokens);
    		text_count++;
    		record_count++;
    	}
    	else if (tokens[0].equals("E") ){
    		record_count++;
    		checkEndRecord(tokens);
    	}
    	else {
    		// ERROR: INVALID RECORD TYPE, MUST EITHER BE A HEADER (H), TEXT (T), OR END (E) RECORD
    		errorsPrint(eHandler.getError(33));
    		outputPrint(eHandler.getError(33));
    	}
    }
    
    private static void checkHeaderRecord (String[] tokens) {
    	/*
    	 *   checkHeaderRecord takes the tokens from the header record and checks for whatever
    	 *   errors you decide to look for. 
    	 *   
    	 *   tokens[0] should always be H
    	 *   tokens[1] should be a valid module name
    	 *   tokens[2] should be a valid load address
    	 *   tokens[3] should be a valid execution address
    	 *   tokens[4] should be the program length
    	 *   tokens[5] - tokens[7]
    	 *   		   should be the date and time of assembly
    	 *   tokens[8] should just be FICKELL-LLM
    	 *   tokens[9] is the version number
    	 *   tokens[10] should be the module name and should match tokens[1]
    	 *   
    	 */
    	 if (tokens.length == 11) {
			 int load_page = 0;
			 int load_address = 0;
			 String program_name = tokens[1];
			 String fickell = tokens[8];
			 String prgm_name_2 = tokens[10]; // MUST MATCH tokens[1]
			 Boolean valid_start = true;
			 Boolean valid_module_length = true;
			 Boolean valid_execution_start = true;
			 Boolean valid_program_names = true;

			 // Check for valid program name 
			 if (!isValidLabel(program_name)) {
				 // ERROR: PROGRAM NAME IS INVALID, MUST BE 2-32 CHARACTERS AND NUMBERS LONG AND MUST BEGIN WITH A LETTER
				 errorsPrint(eHandler.getError(1));
				 outputPrint(eHandler.getError(1));
				 valid_program_names = false;
			 }

			 // Check for valid load page and address
			 if (tokens[2].length() == 6) {
				 if (isValidHex(tokens[2].substring(0,2))) {
					 load_page = (int)Long.parseLong(tokens[2].substring(0,2),16);
					 if (load_page < 0 || load_page > 3) {
						 // ERROR: LOAD PAGE IS INVALID, MUST BE IN RANGE OF 0-3
						 errorsPrint(eHandler.getError(2));
						 outputPrint(eHandler.getError(2));
						 valid_start = false;
					 }
				 }
				 else {
					 // ERROR: LOAD PAGE CONTAINS INVALID HEXADECIMAL SYNTAX
					 errorsPrint(eHandler.getError(3));
					 outputPrint(eHandler.getError(3));
					 valid_start = false;
				 }

				 if (isValidHex(tokens[2].substring(2))) {
					 load_address = (int)Long.parseLong(tokens[2].substring(2),16);
					 if (load_address < 0 || load_address > 4095) {
						 // ERROR: LOAD ADDRESS IS INVALID, MUST BE IN RANGE OF 0-4095
						 errorsPrint(eHandler.getError(4));
						 outputPrint(eHandler.getError(4));
						 valid_start = false;
					 }
				 }
				 else {
					 // ERROR: LOAD ADDRESS CONTAINS INVALID HEXADECIMAL SYNTAX
					 errorsPrint(eHandler.getError(5));
					 outputPrint(eHandler.getError(5));
					 valid_start = false;
				 }
			 }
			 else {
				 // ERROR: LOAD ADDRESS LENGTH MUST BE 6 HEX DIGITS IN LENGTH
				 errorsPrint(eHandler.getError(6));
				 outputPrint(eHandler.getError(6));
				 valid_start = false;
			 }

			 // Check for valid module length
			 if (isValidHex(tokens[4])) {
				 if (tokens[4].length() == 4) {
					 int total_length = (int)Long.parseLong(tokens[4], 16);
					 
					 if (total_length < 0 || total_length > 16383) {
						 // ERROR: INVALID MODULE LENGTH, MUST BE IN RANGE 0-16383
						 errorsPrint(eHandler.getError(7));
						 outputPrint(eHandler.getError(7));
						 valid_module_length = false;

					 }
				 }
				 else {
					 // ERROR: MODULE LENGTH MUST BE 4 HEX DIGITS IN LENGTH
					 errorsPrint(eHandler.getError(8));
					 outputPrint(eHandler.getError(8));
					 valid_module_length = false;
				 }
			 }
			 else {
				 // ERROR: MODULE LENGTH CONTAINS INVALID HEXADECIMAL SYNTAX
				 errorsPrint(eHandler.getError(9));
				 outputPrint(eHandler.getError(9));
				 valid_module_length = false;
			 }

			 // Check for valid execution start address
			 if (isValidHex(tokens[3])) {
				 if (tokens[3].length() == 4) {
					 int execution_address = (int)Long.parseLong(tokens[3], 16);

					 if (execution_address < 0 || execution_address > 4095) {
						 // ERROR: EXECUTION START ADDRESS EXCEEDS THE PROGRAM LENGTH
						 errorsPrint(eHandler.getError(10));
						 outputPrint(eHandler.getError(10));
						 valid_execution_start = false;
					 }
				 }
				 else {
					 // ERROR: EXECUTION START ADDRESS MUST BE 4 HEX DIGITS IN LENGTH
					 errorsPrint(eHandler.getError(11));
					 outputPrint(eHandler.getError(11));
					 valid_execution_start = false;
				 }
			 }
			 else {
				 // ERROR: EXECUTION START ADDRESS CONTAINS INVALID HEXADECIMAL SYNTAX
				 errorsPrint(eHandler.getError(12));
				 outputPrint(eHandler.getError(12));
				 valid_execution_start = false;

			 }

			 // Check to make sure Program Names match up
			 if (!program_name.equals(prgm_name_2)) {
				 // ERROR: PROGRAM NAMES MUST MATCH IN THE HEADER RECORD OF AN OBJECT FILE
				 errorsPrint(eHandler.getError(13));
				 outputPrint(eHandler.getError(13));
				 valid_program_names = false;
			 }

			 // Check for FICKELL to be the machine name
			 if (!fickell.equals("FICKELL-LLM")) {
				 // WARNING: OBJECT FILE SHOULD HAVE BEEN PRODUCED BY A FICKELL ASSEMBLER
				 errorsPrint(eHandler.getError(14));
				 outputPrint(eHandler.getError(14));
			 }


			 // If valid, set correct info to variables
			 if (valid_start && valid_module_length && valid_execution_start && valid_program_names) {
				 exec_address = (int)Long.parseLong(tokens[3], 16);
				 module_length = (int)Long.parseLong(tokens[4], 16);
				 PROGRAM_NAME = program_name;
			 }
			 else {
				 continue_simulation = false;
				 outputPrint("INVALID HEADER RECORD. SIMULATION HAS BEEN STOPPED");		
			 }

		 }
		 else {
			 // ERROR: HEADER RECORDS MUST CONTAIN EXACTLY 11 FIELDS
			 errorsPrint(eHandler.getError(15));
			 outputPrint(eHandler.getError(15));
			 outputPrint("INVALID HEADER RECORD. SIMULATION HAS BEEN STOPPED");
			 continue_simulation = false;
		 }

    }

    private static void checkTextRecord (String[] tokens) {
    	/*
    	 *  checkTextRecord takes the tokens from the text record and checks for whatever errors
    	 *  you need to look for.
    	 *  
    	 *  tokens[0] should be T
    	 *  tokens[1] should be the location
    	 *  tokens[2] should be the actual instruction/data word you're going to be running
    	 *  tokens[3] should the the program name
    	 *  
    	 */
    	 if (tokens.length == 4) {
			 String page_hex = tokens[1].substring(0,2);
			 String location_hex = tokens[1].substring(2);
			 int page = (int)Long.parseLong(page_hex,16);
			 int location = (int)Long.parseLong(location_hex,16);
			 String instruction_data_word = tokens[2];
			 String program_name = tokens[3];
			 boolean valid_location = true;
			 boolean valid_instruction_data_word = true;

			 // Check instruction location 
			 if (tokens[1].length() == 6) {
				 if (isValidHex(page_hex)) {
					 int page_int = (int)Long.parseLong(page_hex, 16);
					 if (page_int < 0 || page_int > 3) {
						 // ERROR: PROGRAM ASSIGNED PAGE VALUE IS INVALID, MUST BE IN RANGE OF 0-3
						 errorsPrint(eHandler.getError(16));
						 outputPrint(eHandler.getError(16));
						 valid_location = false;
					 }
				 }
				 else {
					 // ERROR: PROGRAM ASSIGNED PAGE VALUE CONTAINS INVALID HEXADECIMAL SYNTAX
					 errorsPrint(eHandler.getError(17));
					 outputPrint(eHandler.getError(17));
					 valid_location = false;
				 }
			 }
			 else {
				 // ERROR: PROGRAM ASSIGNED PAGE AND LOCATION COMBINED MUST BE 6 HEX DIGITS IN LENGTH
				 errorsPrint(eHandler.getError(18));
				 outputPrint(eHandler.getError(18));
			 }

			 if (isValidHex(location_hex)) {
				 int loc_int = (int)Long.parseLong(location_hex, 16);
				 if (loc_int < 0 || loc_int > 4095) {
					 // ERROR: PROGRAM ASSIGNED LOCATION VALUE IS INVALID, MUST BE IN RANGE OF 0-16383
					 errorsPrint(eHandler.getError(19));
					 outputPrint(eHandler.getError(19));
					 valid_location = false;
				 }
			 }
			 else {
				 // ERROR: PROGRAM ASSIGNED LOCATION VALUE CONTAINS INVALID HEXADECIMAL SYNTAX
				 errorsPrint(eHandler.getError(20));
				 outputPrint(eHandler.getError(20));
				 valid_location = false;
			 }
			 
			 // Check instruction/data word syntax
			 if (instruction_data_word.length() == 8) {
				 if (!isValidHex(instruction_data_word)) {
					 // ERROR: INSTRUCTION/DATA WORD CONTAINS INVALID HEXADECIMAL SYNTAX
					 errorsPrint(eHandler.getError(21));
					 outputPrint(eHandler.getError(21));
					 valid_instruction_data_word = false;
				 }
			 }
			 else {
				// ERROR: INSTRUCTION/DATA WORD MUST BE 8 HEX DIGITS IN LENGTH
				 errorsPrint(eHandler.getError(22));
				 outputPrint(eHandler.getError(22));
				 valid_instruction_data_word = false;
			 }
			 
			 // VALID TEXT RECORD!!! GET WHAT DATA YOU NEED HERE!
			 if (valid_location && valid_instruction_data_word) {
				 memory[page][location] = instruction_data_word;
			 }
			 // TEXT RECORD INVALID ADD NOP TO MEMORY
			 else
			 {
				 memory[page][location] = "78000000";
			 }

    	 }
			
		 else {
			 // ERROR: TEXT RECORDS MUST CONTAIN EXACTLY 4 FIELDS
			 errorsPrint(eHandler.getError(23));
			 outputPrint(eHandler.getError(23));
			
		 }

    }

    private static void checkEndRecord (String[] tokens) {
    	/*
    	 *  checkEndRecord takes the tokens from the text record and checks for whatever errors
    	 *  you need to look for.
    	 *  
    	 *  tokens[0] should be E
    	 *  tokens[1] should be the total number of records, you may want to make global variables that
    	 *     keeps track of the number of records so you can check
    	 *  tokens[2] should be the total number of text records, probably should make a global variable for this too
    	 *  tokens[3] should the the program name
    	 *  
    	 */
    	if (tokens.length == 4) {
			 String total_records_hex = tokens[1];
			 String total_text_records_hex = tokens[2];
			 String program_name = tokens[3];
			 int total_int = 0;
			 int t_count_int = 0;
			 boolean valid_total = true;
			 boolean valid_t_count = true;
			 boolean valid_program_name = true;

			 // Check total record count
			 if (isValidHex(total_records_hex)) {
				 if (total_records_hex.length() == 4) {
					 total_int = (int)Long.parseLong(total_records_hex, 16);
					 if (total_int != record_count) {
						 // ERROR: THE VALUE OF TOTAL RECORDS IN THE END RECORD DOES NOT MATCH THE TOTAL RECORD COUNT
						 errorsPrint(eHandler.getError(24));
						 outputPrint(eHandler.getError(24));
						 valid_total = false;
					 }
				 }
				 else {
					 // ERROR: TOTAL RECORDS HEX VALUE IN THE END RECORD MUST HAVE A LENGTH OF 4
					 errorsPrint(eHandler.getError(25));
					 outputPrint(eHandler.getError(25));
					 valid_total = false;
				 }
			 }
			 else {
				 // ERROR: THE VALUE OF TOTAL RECORDS CONTAINS INVALID HEXADECIMAL SYNTAX
				 errorsPrint(eHandler.getError(26));
				 outputPrint(eHandler.getError(26));
				 valid_total = false;
			 }

			 // Check text record count
			 if (isValidHex(total_text_records_hex)) {
				 if (total_text_records_hex.length() == 4) {
					 t_count_int = (int)Long.parseLong(total_text_records_hex, 16);
					 if (t_count_int != text_count) {
						 // ERROR: THE VALUE OF TOTAL TEXT RECORDS IN THE END RECORD DOES NOT MATCH THE TEXT RECORD COUNT
						 errorsPrint(eHandler.getError(27));
						 outputPrint(eHandler.getError(27));
						 valid_t_count = false;
					 }
					 else if (t_count_int > module_length) {
						 // ERROR: NUMBER OF TEXT RECORDS EXCEED THE MODULES LENGTH
						 errorsPrint(eHandler.getError(28));
						 outputPrint(eHandler.getError(28));
						 valid_t_count = false;
					 }
				 }
				 else {
					 // ERROR: TOTAL TEXT RECORDS HEX VALUE IN THE END RECORD MUST HAVE A LENGTH OF 4
					 errorsPrint(eHandler.getError(29));
					 outputPrint(eHandler.getError(29));
					 valid_t_count = false;
				 }
			 }
			 else {
				 // ERROR: THE VALUE OF TOTAL TEXT RECORDS CONTAINS INVALID HEXADECIMAL SYNTAX
				 errorsPrint(eHandler.getError(30));
				 outputPrint(eHandler.getError(30));
				 valid_t_count = false;
			 }
			 
			 // Check for matching program name
			 if (!program_name.equals(PROGRAM_NAME)) {
				 // ERROR: PROGRAM NAME IN THE END RECORD DOES NOT MATCH THE MODULES NAME
				 errorsPrint(eHandler.getError(31));
				 outputPrint(eHandler.getError(31));
				 
			 }
			 
			 
			 // VALID END RECORD!!!!!! NOT SURE IF YOU NEED ANYTHING FROM HERE BUT ILL LEAVE THIS HERE JUST IN CASE
			 if (valid_total && valid_t_count && valid_program_name) {
				 //get data here
				 valid_end = true;
			 }
			 

		 }
		 else {
			 // ERROR: END RECORDS MUST HAVE EXACTLY 6 FIELDS
			 errorsPrint(eHandler.getError(32));
			 outputPrint(eHandler.getError(32));
			 
		 }
    }

    private static String hexToBinary (String hex) {
    	int i = 0;
    	String binary = "";

    	while (i < hex.length()) {
    		char temp = hex.charAt(i);
    		int character_int = Character.getNumericValue(temp);
    		String ch_bin = extendBinary(Integer.toBinaryString(character_int), 4);
    		binary += ch_bin;
    		i++;
    	}
    	return binary;
    }
    
    private static boolean isValidLabel (String label) {
    	boolean check = true, valid_characters = false, valid_length = true, valid_lead_ch = true, answer = false;
        char[] characters = label.toCharArray();
        int i = 0;
        
            // Check leading character
            if (!(Character.isLowerCase(characters[0])) && !(Character.isUpperCase(characters[0]))) {
                valid_lead_ch = false;
            }
            // Check each character of label
            while (i < label.length() && check) {
                if (Character.isLowerCase(characters[i]) || Character.isUpperCase(characters[i]) || Character.isDigit(characters[i])) {    
                    valid_characters = true;
                }
                else {
                    check = false;
                    valid_characters = false;
                }
                i++;
            }
            // Check length of label
            if (!(label.length() <= 32) || !(label.length() > 0)) {
                valid_length = false;
            }  
            
            // Set valid_symbol to true to update to table
            if (valid_lead_ch && valid_characters && valid_length) {
            	answer = true;
            }
            return answer;
    }
    
    private static Boolean isValidHex (String hex) {
    	boolean answer = false;
    	
    	if (hex.matches("[A-F0-9]+")) {
    		answer = true;
    	}
    	else {
    		answer = false;
    	}
    	return answer;
    }
    
    private static String extendBinary (String binary, int digits) {
        while (binary.length() < digits) {
            binary = "0" + binary;
        }
        return binary;
    }
    
	public static void inputPrint(String str){
        SimulatorFrame.getInputArea().append(str + newline);
    }
	
	public static void outputPrint(String str){
        SimulatorFrame.getOutputArea().append(str + newline);
    }
	
	public static void errorsPrint(String str){
        SimulatorFrame.getErrorsArea().append(str + newline);
    }
}
